﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace SPMS.Log.Utility
{
    /// <summary>
    /// 线程安全字典
    /// </summary>
    /// <remarks>提供线程安全的字典实现</remarks>
    /// <history>
    /// [zanezeng]               2009/10/12 10:31    创建
    /// </history>
    public sealed class SynchronizedDictionary<TKey, TValue> : IDictionary<TKey, TValue>
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类型<see cref="SynchronizedDictionary&lt;TKey, TValue&gt;"/>的新实例
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 13:58    创建
        /// </history>
        public SynchronizedDictionary()
            : this( null )
        {
        }

        /// <summary>
        /// 初始化类型<see cref="SynchronizedDictionary&lt;TKey, TValue&gt;"/>的新实例
        /// </summary>
        /// <param name="comparer">比较键时要使用的<see cref="IEqualityComparer&lt;T&gt;"/>实现，或者为<c>Null</c>引用，以便为键类型使用默认的<see cref="EqualityComparer&lt;T&gt;"/>。</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 13:59    创建
        /// </history>
        public SynchronizedDictionary( IEqualityComparer<TKey> comparer )
        {
            //记录参数
            this.m_Comparer = comparer;

            //创建数据字典
            this.m_Data = new Dictionary<TKey, TValue>( this.m_Comparer );
        }

        #endregion

        #region ---IDictionary<TKey,TValue>

        /// <summary>
        /// 在<see cref="T:System.Collections.Generic.IDictionary`2"/>对象中添加一个带有所提供的键和值的元素
        /// </summary>
        /// <param name="key">用作要添加的元素的键</param>
        /// <param name="value">用作要添加的元素的值</param>
        /// <exception cref="T:System.ArgumentNullException">
        /// 	<paramref name="key"/>为Null
        /// </exception>
        /// <exception cref="T:System.ArgumentException">
        /// <see cref="T:System.Collections.Generic.IDictionary`2"/>中已经存在包含相同键的元素
        /// </exception>
        /// <exception cref="T:System.NotSupportedException">
        /// <see cref="T:System.Collections.Generic.IDictionary`2"/>为只读或者具有固定大小
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 11:22    创建
        /// </history>
        public void Add( TKey key, TValue value )
        {
            //同步
            lock (this.m_Data)
            {
                //添加元素
                this.m_Data.Add( key, value );

                //重置数据缓存
                this.m_DataCache = null;
            }
        }

        /// <summary>
        /// 判断<see cref="T:System.Collections.Generic.IDictionary`2"/>对象是否包含具有指定键的元素
        /// </summary>
        /// <param name="key">要在<see cref="T:System.Collections.Generic.IDictionary`2"/>对象中定位的键</param>
        /// <returns>
        /// 	<c>True</c>：<see cref="T:System.Collections.Generic.IDictionary`2"/>包含带有该键的元素<br/>
        /// 	<c>False</c>：<see cref="T:System.Collections.Generic.IDictionary`2"/>不包含带有该键的元素
        /// </returns>
        /// <exception cref="T:System.ArgumentNullException">
        /// 	<paramref name="key"/> is null.
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 11:24    创建
        /// </history>
        public bool ContainsKey( TKey key )
        {
            return this.DataCache.ContainsKey( key );
        }

        /// <summary>
        /// 获得<see cref="T:System.Collections.Generic.ICollection`1"/>包含<see cref="T:System.Collections.Generic.IDictionary`2"/>对象中包含的所有元素的键
        /// </summary>
        /// <value></value>
        /// <returns>
        /// 包含<see cref="T:System.Collections.Generic.IDictionary`2"/>对象中包含的所有元素的键的<see cref="T:System.Collections.Generic.ICollection`1"/>对象
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 11:26    创建
        /// </history>
        public ICollection<TKey> Keys
        {
            get
            {
                return this.DataCache.Keys;
            }
        }

        /// <summary>
        /// 从<see cref="T:System.Collections.Generic.IDictionary`2"/>对象中移除带有指定键的元素
        /// </summary>
        /// <param name="key">要移除的元素的键</param>
        /// <returns>
        /// 	<c>True</c>：从<see cref="T:System.Collections.Generic.IDictionary`2"/>对象中移除带有指定键的元素<br/>
        /// 	<c>False</c>：<see cref="T:System.Collections.Generic.IDictionary`2"/>不包含带有该键的元素
        /// </returns>
        /// <exception cref="T:System.ArgumentNullException">
        /// 	<paramref name="key"/>为Null
        /// </exception>
        /// <exception cref="T:System.NotSupportedException">
        /// <see cref="T:System.Collections.Generic.IDictionary`2"/>为只读
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 11:28    创建
        /// </history>
        public bool Remove( TKey key )
        {
            //同步
            lock (this.m_Data)
            {
                //删除元素
                bool isSuccess = this.m_Data.Remove( key );

                //重置数据缓存
                this.m_DataCache = null;

                //返回
                return isSuccess;
            }
        }

        /// <summary>
        /// 获得带有指定键的元素的值
        /// </summary>
        /// <param name="key">要获得的元素的键</param>
        /// <param name="value"> 带有指定键的元素的值</param>
        /// <returns>
        /// 	<c>True</c>：从<see cref="T:System.Collections.Generic.IDictionary`2"/>包含带有该键的元素<br/>
        /// 	<c>False</c>：<see cref="T:System.Collections.Generic.IDictionary`2"/>不包含带有该键的元素
        /// </returns>
        /// <exception cref="T:System.ArgumentNullException">
        /// 	<paramref name="key"/>为Null
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 11:30    创建
        /// </history>
        public bool TryGetValue( TKey key, out TValue value )
        {
            return this.DataCache.TryGetValue( key, out value );
        }

        /// <summary>
        /// 获得包含<see cref="T:System.Collections.Generic.IDictionary`2"/>对象中所有元素的值的<see cref="T:System.Collections.Generic.ICollection`1"/>对象
        /// </summary>
        /// <value></value>
        /// <returns>
        /// 包含<see cref="T:System.Collections.Generic.IDictionary`2"/>对象中所有元素的值的<see cref="T:System.Collections.Generic.ICollection`1"/>对象
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 11:32    创建
        /// </history>
        public ICollection<TValue> Values
        {
            get
            {
                return this.DataCache.Values;
            }
        }

        /// <summary>
        /// 获取或者设置指定索引处的元素
        /// </summary>
        /// <value>指定索引处的元素</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 11:33    创建
        /// </history>
        public TValue this[TKey key]
        {
            get
            {
                return this.DataCache[key];
            }
            set
            {
                //同步
                lock (this.m_Data)
                {
                    //设置值
                    this.m_Data[key] = value;

                    //重置数据缓存
                    this.m_DataCache = null;
                }
            }
        }

        #endregion

        #region ---ICollection<KeyValuePair<TKey,TValue>>

        /// <summary>
        /// 向集合<see cref="T:System.Collections.Generic.ICollection`1"/>中添加一个项目
        /// </summary>
        /// <param name="item">要添加到集合<see cref="T:System.Collections.Generic.ICollection`1"/>中的项目</param>
        /// <exception cref="T:System.NotSupportedException">
        /// 集合<see cref="T:System.Collections.Generic.ICollection`1"/>是一个只读集合
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 10:35    创建
        /// </history>
        public void Add( KeyValuePair<TKey, TValue> item )
        {
            //同步
            lock (this.m_SyncRoot)
            {
                //清除数据
                ((ICollection<KeyValuePair<TKey, TValue>>)(this.m_Data)).Add( item );

                //重置数据缓存
                this.m_DataCache = null;
            }
        }

        /// <summary>
        /// 清除集合<see cref="T:System.Collections.Generic.ICollection`1"/>中的所有项目
        /// </summary>
        /// <exception cref="T:System.NotSupportedException">
        /// 集合<see cref="T:System.Collections.Generic.ICollection`1"/>是一个只读集合
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 10:36    创建
        /// </history>
        public void Clear()
        {
            //同步
            lock (this.m_SyncRoot)
            {
                //清除数据
                this.m_Data.Clear();

                //重置数据缓存
                this.m_DataCache = null;
            }
        }

        /// <summary>
        /// 判断集合<see cref="T:System.Collections.Generic.ICollection`1"/>中是否包含给定的项目
        /// </summary>
        /// <param name="item">要判断是否包含在集合<see cref="T:System.Collections.Generic.ICollection`1"/>中的项目</param>
        /// <returns>
        /// 	<c>True</c>：给定的项目包含在集合中<br/>
        /// 	<c>False</c>：给定的项目没有包含在集合中
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 10:37    创建
        /// </history>
        public bool Contains( KeyValuePair<TKey, TValue> item )
        {
            return ((ICollection<KeyValuePair<TKey, TValue>>)(this.DataCache)).Contains( item );
        }

        /// <summary>
        /// 从给定的<see cref="T:System.Array"/>索引开始，将<see cref="T:System.Collections.Generic.ICollection`1"/>中的所有元素拷贝到<see cref="T:System.Array"/>中
        /// </summary>
        /// <param name="array">作为从<see cref="T:System.Collections.Generic.ICollection`1"/>复制的元素的目标位置的一维<see cref="T:System.Array"/>。<see cref="T:System.Array"/>必须具有从零开始的索引</param>
        /// <param name="arrayIndex"><see cref="T:System.Array"/>中从零开始的索引，从此处开始复制</param>
        /// <exception cref="T:System.ArgumentNullException">
        /// 	<paramref name="array"/>为Null
        /// </exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">
        /// 	<paramref name="arrayIndex"/>小于0
        /// </exception>
        /// <exception cref="T:System.ArgumentException">
        /// 	<paramref name="array"/>为多维数组
        /// -或者-
        /// <paramref name="arrayIndex"/>等于或者大于<paramref name="array"/>的总长度
        /// -或者-
        /// <see cref="T:System.Collections.Generic.ICollection`1"/>中项目的总数大于从<paramref name="arrayIndex"/>开始到目标<paramref name="array"/>结尾之间的可用空间
        /// -或者-
        /// 无法将<c>KeyValuePair&lt;TKey, TValue&gt;</c>转化为目标<paramref name="array"/>的类型
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 10:38    创建
        /// </history>
        public void CopyTo( KeyValuePair<TKey, TValue>[] array, int arrayIndex )
        {
            ((ICollection<KeyValuePair<TKey, TValue>>)(this.DataCache)).CopyTo( array, arrayIndex );
        }

        /// <summary>
        /// 获得集合<see cref="T:System.Collections.Generic.ICollection`1"/>中包含的项目总数
        /// </summary>
        /// <value></value>
        /// <returns>
        /// 集合<see cref="T:System.Collections.Generic.ICollection`1"/>中包含的项目总数
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 10:43    创建
        /// </history>
        public int Count
        {
            get
            {
                return this.DataCache.Count;
            }
        }

        /// <summary>
        /// 获得一个值，该值用于判断集合<see cref="T:System.Collections.Generic.ICollection`1"/>是否为只读集合
        /// </summary>
        /// <value></value>
        /// <returns>
        /// 	<c>True</c>：当前集合为只读集合<br/>
        /// 	<c>False</c>：当前集合为读写集合
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 10:43    创建
        /// </history>
        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 从集合<see cref="T:System.Collections.Generic.ICollection`1"/>中删除一个项目
        /// </summary>
        /// <param name="item">要从集合<see cref="T:System.Collections.Generic.ICollection`1"/>中删除的项目</param>
        /// <returns>
        /// 	<c>True</c>：给定的项目从集合中成功删除<br/>
        /// 	<c>False</c>：给定的项目从集合中删除失败
        /// </returns>
        /// <exception cref="T:System.NotSupportedException">
        /// 集合<see cref="T:System.Collections.Generic.ICollection`1"/>是一个只读集合
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 10:47    创建
        /// </history>
        public bool Remove( KeyValuePair<TKey, TValue> item )
        {
            //同步
            lock (this.m_SyncRoot)
            {
                //删除
                bool isSuccess = ((ICollection<KeyValuePair<TKey, TValue>>)(this.m_Data)).Remove( item );

                //清除数据换粗
                this.m_DataCache = null;

                //返回结果
                return isSuccess;
            }
        }

        #endregion

        #region ---IEnumerable<KeyValuePair<TKey,TValue>>

        /// <summary>
        /// 获得当前集合的枚举器
        /// </summary>
        /// <returns>
        /// 用于迭代当前集合的<see cref="T:System.Collections.IEnumerator"/>对象
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 10:34    创建
        /// </history>
        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return this.DataCache.GetEnumerator();
        }

        #endregion

        #region ---IEnumerable

        /// <summary>
        /// 获得当前集合的枚举器
        /// </summary>
        /// <returns>
        /// 用于迭代当前集合的<see cref="T:System.Collections.IEnumerator"/>对象
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 10:34    创建
        /// </history>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.DataCache.GetEnumerator();
        }

        #endregion

        #region ---Proeprty

        /// <summary>
        /// 获得数据缓存
        /// </summary>
        /// <value>数据缓存</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 11:18    创建
        /// </history>
        private Dictionary<TKey, TValue> DataCache
        {
            get
            {
                //判断数据缓存是否创建
                if (null != this.m_DataCache)
                {
                    //如果已经创建，则直接返回数据缓存
                    return this.m_DataCache;
                }

                //同步
                lock (this.m_SyncRoot)
                {
                    //判断数据缓存是否创建
                    if (null != this.m_DataCache)
                    {
                        //如果已经创建，则直接返回数据缓存
                        return this.m_DataCache;
                    }

                    //创建数据缓存
                    this.m_DataCache = new Dictionary<TKey, TValue>( this.m_Data, this.m_Comparer );
                }

                //返回数据缓存
                return this.m_DataCache;
            }
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 数据
        /// </summary>
        private Dictionary<TKey, TValue> m_Data;

        /// <summary>
        /// 比较键时使用的比较器
        /// </summary>
        private IEqualityComparer<TKey> m_Comparer;

        /// <summary>
        /// 数据缓存
        /// </summary>
        private Dictionary<TKey, TValue> m_DataCache;

        /// <summary>
        /// 同步对象
        /// </summary>
        private object m_SyncRoot = new object();

        #endregion
    }
}
